﻿using Draco.OWF.Metadata.Impl;
using System;
using System.Collections.Generic;
using System.Xml.Serialization;

namespace Draco.OWF.Metadata
{
    [XmlInclude(typeof(WorkflowModelImpl))]
    public abstract class WorkflowModel : IScope
    {
        protected String m_Id = Guid.NewGuid().ToString();
        protected List<ActivityModel> m_Activities = new List<ActivityModel>();
        protected List<RouteModel> m_Routes = new List<RouteModel>();
        protected IDictionary<String, Object> m_variables = new Dictionary<String, Object>();
        protected ActivityModel m_EndActivity;

        public WorkflowModel() : this("", "") { }
        public WorkflowModel(String name) : this("", name) { }
        public WorkflowModel(String id, String name)
        {
            if (String.IsNullOrEmpty(name))
                name = "untitled workflow";
            this.Id = id;
            this.Name = name;
            this.Header = new WorkflowHeader();
            this.Header.CreateDate = DateTime.Now;
        }


        [XmlAttribute("id")]
        public virtual string Id
        {
            get { return m_Id; }
            set
            {
                if (!String.IsNullOrEmpty(value))
                    m_Id = value;
            }
        }

        [XmlAttribute("name")]
        public virtual String Name { get; set; }

        [XmlElement(ElementName = "ProcessHeader", Type = typeof(WorkflowHeader), IsNullable = false, Order = 1)]
        public WorkflowHeader Header { get; set; }

        [XmlArray("Activities", Order = 2)]
        [XmlArrayItem("Activity", Type = typeof(ActivityModel), IsNullable = false)]
        public virtual List<ActivityModel> Activities
        {
            get { return m_Activities; }
            set { this.m_Activities = value; }
        }

        [XmlArray("Transitions", Order = 3)]
        [XmlArrayItem("Transition", Type = typeof(RouteModel), IsNullable = false)]
        public virtual List<RouteModel> Routes
        {
            get { return m_Routes; }
            set { this.m_Routes = null; }
        }

        [XmlIgnore]
        public IDictionary<String, Object> Variables
        {
            get
            {
                return this.m_variables;
            }
        }

        #region
        [XmlIgnore]
        public abstract bool Readonly { get; set; }
        
        [XmlIgnore]
        public abstract ActivityModel EndActivity { get; set; }

        public abstract ActivityModel GetEntry();
        public abstract ActivityModel GetActivity(String activityId);
        public abstract RouteModel GetRoute(String routeId);
        public abstract RouteModel GetRoute(String fromAcId, String toAcId);
        public abstract List<ActivityModel> GetNextActivities(String activityId);
        public abstract List<ActivityModel> GetPreviousActivities(String activityId);

        public abstract List<RouteModel> GetFromActivityRoutes(String activityId);
        public abstract List<RouteModel> GetToActivityRoutes(String activityId);

        public abstract void AddActivity(ActivityModel activity);
        public abstract void AddRoute(RouteModel route);
        public abstract void RemoveActivity(String activityId);
        public abstract void RemoveRoute(String routeId);
        public abstract void Clear();
        public abstract bool Check();
        #endregion
    }
}
